<template>
  <div class="callback-container">
    <!-- 加载状态 -->
    <div v-if="loading" class="loading-wrapper">
      <i class="el-icon-loading"></i>
      <p class="loading-text">{{ loadingText }}</p>
    </div>

    <!-- 错误状态 -->
    <div v-if="error" class="error-wrapper">
      <el-alert
        title="登录授权失败"
        type="error"
        :closable="false"
        show-icon
        center
      >
        <p class="error-detail">{{ errorMessage }}</p>
        <div class="action-buttons">
          <el-button type="primary" @click="retryLogin" size="small">
            <i class="el-icon-refresh"></i> 重新尝试
          </el-button>
          <el-button @click="goToLogin" size="small">
            <i class="el-icon-s-home"></i> 返回登录
          </el-button>
        </div>
      </el-alert>
    </div>
  </div>
</template>

<script>
import { RedirectStorage } from '@/permission'

export default {
  name: 'SSOCallback',
  data() {
    return {
      loading: true,
      loadingText: '正在与认证服务器通信...',
      error: false,
      errorMessage: '',
      retryCount: 0,
      maxRetries: 3
    }
  },
  created() {
    this.handleCallback()
  },
  methods: {
    async handleCallback() {
      try {
        console.debug('[SSO回调] 开始处理回调参数:', this.$route.query)
        
        // 第一步：获取并验证Token参数
        const token = this.getTokenFromQuery()
        console.info('[SSO回调] 获取到认证Token:', token ? '存在' : '不存在')

        // 第二步：提交登录操作
        this.loadingText = '正在验证访问令牌...'
        await this.$store.dispatch('user/login', token)
        
        // 第三步：获取用户信息
        this.loadingText = '正在加载用户信息...'
        await this.$store.dispatch('user/getInfo')

        // 第四步：处理重定向逻辑
        await this.handleRedirect()

      } catch (error) {
        await this.handleError(error)
      } finally {
        this.loading = false
      }
    },

    // 从URL参数获取Token（增强版）
    getTokenFromQuery() {
      const query = this.$route.query
      const possibleKeys = ['token', 'access_token', 'authToken']
      
      // 增加URL参数解码处理
      const tokenKey = possibleKeys.find(key => {
        const value = query[key]
        return value && typeof value === 'string' && value.trim().length > 0
      })

      if (!tokenKey) {
        throw new Error('未找到有效的授权令牌参数')
      }

      // 处理URL编码的情况
      try {
        return decodeURIComponent(query[tokenKey])
      } catch (e) {
        console.warn('[SSO回调] Token解码失败:', e)
        return query[tokenKey]
      }
    },

    // 处理重定向逻辑（安全增强）
    async handleRedirect() {
      let redirectPath = RedirectStorage.get() || '/'
      
      // 安全校验：防止开放重定向
      if (!this.isValidRedirectPath(redirectPath)) {
        console.warn('[SSO回调][重定向] 检测到无效路径:', redirectPath)
        redirectPath = '/'
      }

      console.info('[SSO回调][重定向] 准备跳转到:', redirectPath)

      try {
        await this.$router.replace(redirectPath)
      } catch (error) {
        console.error('[SSO回调][重定向] 跳转异常:', error)
        await this.safeRedirectToHome()
      }
    },

    // 路径有效性验证
    isValidRedirectPath(path) {
      return (
        typeof path === 'string' &&
        path.startsWith('/') &&  // 必须相对路径
        !path.includes('//') &&  // 防止路径穿越
        !path.startsWith('/\\') // 额外安全校验
      )
    },

    // 安全跳转到首页
    async safeRedirectToHome() {
      try {
        await this.$router.replace('/')
      } catch (error) {
        console.error('[SSO回调][紧急跳转] 无法返回首页:', error)
        window.location.href = '/'
      }
    },

    // 统一错误处理（增强版）
    async handleError(error) {
      console.error('[SSO回调] 认证异常:', error)
      
      // 清除可能的无效Token
      try {
        await this.$store.dispatch('user/resetToken')
      } catch (e) {
        console.warn('[SSO回调] Token清除异常:', e)
      }

      // 构建友好错误提示
      this.error = true
      this.errorMessage = this.parseErrorMessage(error)
      
      // 自动跳转保护
      this.autoFallbackTimer = setTimeout(() => {
        this.goToLogin()
      }, 5000)
    },

    // 错误信息解析（增强版）
    parseErrorMessage(rawError) {
      const errorMap = {
        'invalid token': '令牌格式无效',
        'token expired': '登录会话已过期',
        'network error': '无法连接认证服务器',
        '401': '身份验证已过期',
        '403': '没有访问权限'
      }

      const message = String(rawError.message || rawError).toLowerCase()
      
      // 优先匹配已知错误类型
      for (const [key, value] of Object.entries(errorMap)) {
        if (message.includes(key)) {
          return value
        }
      }

      // 处理HTTP状态码
      const statusCode = rawError.response?.status
      if (statusCode && errorMap[statusCode]) {
        return errorMap[statusCode]
      }

      return '系统服务暂时不可用，请稍后再试'
    },

    // 重新尝试登录（带指数退避）
    async retryLogin() {
      if (this.retryCount >= this.maxRetries) {
        this.goToLogin()
        return
      }

      this.retryCount++
      this.error = false
      this.loading = true
      
      // 指数退避延迟
      const delay = Math.min(1000 * (2 ** this.retryCount), 10000)
      await new Promise(resolve => setTimeout(resolve, delay))
      
      try {
        await this.handleCallback()
      } catch (error) {
        await this.handleError(error)
      }
    },

    // 跳转到登录页（安全模式）
    goToLogin() {
      clearTimeout(this.autoFallbackTimer)
      RedirectStorage.clear()
      
      // 双重跳转保护
      if (this.$route.path !== '/login') {
        this.$router.replace('/login').catch(() => {
          window.location.href = '/login'
        })
      }
    }
  },
  beforeDestroy() {
    clearTimeout(this.autoFallbackTimer)
  }
}
</script>

<style scoped>
.callback-container {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #f0f2f5;
}

.loading-wrapper, .error-wrapper {
  text-align: center;
  padding: 20px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.el-icon-loading {
  font-size: 30px;
  color: #409eff;
  animation: rotating 2s linear infinite;
  margin-bottom: 15px;
}

.loading-text {
  color: #606266;
  font-size: 14px;
  letter-spacing: 1px;
  max-width: 300px;
}

.error-detail {
  margin: 10px 0;
  color: #f56c6c;
  font-size: 13px;
  word-break: break-word;
}

.action-buttons {
  margin-top: 15px;
  display: flex;
  gap: 10px;
  justify-content: center;
}

@keyframes rotating {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}


</style>